#pragma once

class analysis
{
public:
	std::vector<code> codes;
	std::vector<object_info> types;
	std::vector<method_info> methods;
	std::vector<describe_info> describes;
	std::vector<std::wstring> vars;
private:
	token_stream& ts;
public:
	analysis(token_stream& t_s) :ts(t_s) {}

private:
	void analy_object();
	void analy_method();
	void analy_describe();
	void analy_code();
public:
	void analy();
private:
	std::wstring get_word(wchar_t);
	argument get_argument()
	{
		argument ret;
		Token t = ts.get_token();
		if (t.type != KEYWORD_TOKEN || t.wchar != HAVE_TOKEN)
			throw Error("Bad Expression", __FILE__, __LINE__);
		std::wstring word;
		while (true)
		{
			t = ts.get_token();
			if (t.type == MARK_TOKEN)
				word += t.wchar;
			else 
			{
				ret.name = word;
				break;
			}
		}
		ts.putback(t);
		return ret;
	}
	code get_method_code()
	{
		if (ts.eof()) return code();
		code c;
		Token t = ts.get_token();
		while (true)
		{
			switch (t.type)
			{
			case SYMBAL_TOKEN:
				if (t.wchar == END_TOKEN)
				{
					c.tokens.push_back(t);
					return c;
				}
				c.tokens.push_back(t);
				break;
			case MARK_TOKEN:
				ts.putback(t);
				t = find_word();
				if (t.type == NONE_TOKEN)
					throw Error("Name Not Define", __FILE__, __LINE__);
				c.tokens.push_back(t);
				break;
			default:
				c.tokens.push_back(t);
				break;
			}
			if (ts.eof())
				throw Error("Bad Ending", __FILE__, __LINE__);
			t = ts.get_token();
		}
		return code();
	}
	object_info get_object_info(std::wstring n)
	{
		for (object_info o : types)
		{
			if (o.name == n)
				return o;
		}
		return none_type_info;
	}
	Token find_word();
};

